﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DNASequencing.core.Algorithms
{
    class SequenceUtils
    {
        public static int extractNegativeError(List<Oligonucleotide> list)
        {
            int error = 0;
            foreach (Oligonucleotide o in list)
                if (o.error > 0)
                    error += o.error;
            return error;
        }

        public static int extractPositiveError(List<Oligonucleotide> list, List<Oligonucleotide> all)
        {
            return all.Count - list.Count;
        }

        //public static int sequencePositiveError(List<Oligonucleotide> list, List<Oligonucleotide> all)
        //{
        //    return extractPositiveError(list, all) - 1;
        //}

        public static int sequenceNegativeError(List<Oligonucleotide> list, Oligonucleotide el)
        {
            return extractNegativeError(list) + el.error;
        }

        /// <summary>
        /// Returns list contains <code>el</code> from <code>source</code>!
        /// </summary>
        /// <param name="el"></param>
        /// <param name="source"></param>
        /// <returns></returns>
        public static List<Oligonucleotide> getBestFollowingSequence(Oligonucleotide el, List<Oligonucleotide> source)
        {
            List<Oligonucleotide> res = new List<Oligonucleotide>();
            bool inserting = false;
            foreach (Oligonucleotide o in source)
            {
                if (o.originalSequence == el.originalSequence)
                    inserting = true;
                if (inserting)
                    res.Add(o);
            }
            return res;
        }

        public static int sequenceLength(List<Oligonucleotide> sequence, Oligonucleotide olig)
        {
            if (sequence.Count == 0)
                return 0;

            int errors = 0;
            foreach (Oligonucleotide o in sequence)
                errors += o.error;
            errors += olig.error;
            return sequence.Count + 1 + (sequence.ElementAt(0).originalSequence.Length - 1) + errors;
        }

        public static bool isBetterSequence(List<Oligonucleotide> temp, List<Oligonucleotide> curr)
        {
            if (temp.Count > curr.Count)
                return true;
            else if (temp.Count == curr.Count)
            {
                int tempError = 0;
                int currError = 0;
                foreach (Oligonucleotide o in temp)
                    tempError += o.error;
                foreach (Oligonucleotide o in curr)
                    currError += o.error;
                if (tempError < currError)
                    return true;
            }
            return false;
        }

        public static List<Oligonucleotide> getNotUsed(List<Oligonucleotide> result, List<Oligonucleotide> all)
        {
            List<Oligonucleotide> notUsed = new List<Oligonucleotide>();

            foreach (Oligonucleotide olig in all)
            {
                bool contains = false;
                foreach (Oligonucleotide olig2 in result)
                    if (olig.originalSequence == olig2.originalSequence)
                    {
                        contains = true;
                        break;
                    }

                if (!contains)
                    notUsed.Add(olig);
            }
            return notUsed;
        }

        public static String sequenceListToString(List<Oligonucleotide> list)
        {
            String sequence = "";
            for (int i = 0; i < list.Count; ++i)
                if (i == 0)
                    sequence += list.ElementAt(i).originalSequence;
                else
                    sequence += list.ElementAt(i).originalSequence.Substring(list.ElementAt(i).originalSequence.Length - list.ElementAt(i).error - 1);
            return sequence;
        }

        public static List<Oligonucleotide> mergeSequences(List<Oligonucleotide> list1, List<Oligonucleotide> list2)
        {
            list2[0].error = list2[0].originalSequence.Length - 1;
            List<Oligonucleotide> result = new List<Oligonucleotide>();
            result.AddRange(list1);
            result.AddRange(list2);
            return result;
        }
    }
}
